<?php
use module\home\model\User;
use module\home\model\Profile;
use module\home\model\Share;
use module\home\model\FriendRequest;

/**
 * load some required classes
 */
require_once MODEL_DIR . '/User.php';
require_once MODEL_DIR . '/Profile.php';
require_once MODEL_DIR . '/Friend.php';
require_once MODEL_DIR . '/Share.php';
require_once MODEL_DIR . '/FriendRequest.php';

/**
 * defining some constatns used in this controller
 */
define('USER_LOGIN_ID', 'USER_LOGIN_ID');
define('URL_PROFILE', '/user/profile/');
define('URL_UPDATE', '/user/update');
define('URL_LOGIN', '/user/login');
define('URL_LIST', '/user/list/');
define('URL_FRIENDS', '/user/friends/');
define('URL_ADDFRIEND', '/user/addfriend/');
define('URL_ADDREQUEST', '/user/addrequest/');
define('URL_DELETEREQUEST', '/user/deleterequest/');
define('URL_REQUESTS', '/user/listrequests/');

/*
 * User Action Controller
 * 
 * extends from Action controller
 * handles user registration, login, logout, and profile viewing
 *
 * @package yasns
 * @subpackage controller
 */
class UserActionController extends ActionController
{

	/** 
	 * default user action (http://domain.com/user)
	 *
	 * implementation is done in the view script
	 */
	public function executeIndex()
	{	
		
	}

	/**
	 * user registration
	 * 
	 * performs user form submission processing
	 * on form submission, validate user inputs
	 * if validation passes, check if there is duplication of username
	 * if no errors, create the user and redirect to profile with message
	 */
	public function executeRegister()
	{
      // initialize view
		$errors = array();
		
		// on form post
		if (isset($_POST, $_POST['submitRegister']) && ($_POST['submitRegister'] == 'submit')) {					
			// initialize form vars
			$username = $_POST['user'];
			$password = $_POST['pass'];
			$confpassword = $_POST['confpass'];
			$username_min_length = 5;
			$username_max_length = 16;
			$password_min_length = 5;

			/*
			 * validating user inputs
			 */
			// validate username
			if (empty($username) || empty($password)) {
				$errors[] = 'Both Username and Password are required.';
			} else {
				if (!Validator::isAlphaNum($username)) {
					$errors[] = 'Username cannot be empty and must have only letters and numbers.';
				}

				if (!Validator::isStringLength($username, $username_min_length, $username_max_length)) {
					$errors[] = "Username must be between {$username_min_length} and {$username_max_length} characters.";
				}

				// validate password
				if (!Validator::isStringLength($password, $password_min_length)) {
					$errors[] = "Password cannot be empty and must be {$password_min_length} characters.";
				}

				if ($password != $confpassword) {
					$errors[] = 'Password and Confirm Password do not match.';
				}
			}
			// validate and create user if account is not in use
			// check if username is available for registration
			$duplicateUser = User::findByUsername($username);

			// check if account is already registered
			if ($duplicateUser) { 
				$errors[] = "Username is not available for registration. Please select another username."; 
			} 
			
			/*
			 * checking for any errors
			 * if not, we will continue with registration process
			 */
			if (empty($errors)) {
				// hash the password
				$password = md5($password);

				// create user
				$user = new User();
				$user->username = $username;
				$user->password = $password;
				$success = $user->insert();

				// redirect to profile on success
				if ($success) {
					Common::flashMessage("Your registration is successful. Please login with your credentials.");
					Common::redirect(URL_LOGIN);
				}
			}
		}
		
		
		// setup view script variables
		$this->errorMessage = current($errors);
	}
	
	/**
	 * user login
	 * 
	 * if user has already logged in, redirect to profile
	 * otherwise validate user input on login form
	 * on successful login, redirect user to profile
	 */
	public function executeLogin()
	{
      // initialize view
		$errors = array();
		
		// on form post
		if (isset($_POST, $_POST['submitLogin']) && ($_POST['submitLogin'] == 'submit')) {
			// initialize form vars
			// initialize username
			$username = $_POST['user'];
			$password = $_POST['pass'];
			
			// validate username and password
			if (Validator::isEmpty($username) || Validator::isEmpty($password)) {
				$errors[] = 'Username & Password cannot be empty';
			}

			if(empty($errors)) {
				// hash password
				$password = md5($password);

				// check if username exists
				$success = Auth::authenticate($username, $password);

				// false, prompt error
				if(!$success) { 
					$errors[] = "User does not exist or entry error. Please try again!"; 
				} else {
					// true, redirect to profile
					Common::redirect(URL_PROFILE);
				}	
			}
		}
		
		
		$this->errorMessage = current($errors);
	}
	
	/**
	 * user logout 
	 * 
	 * destroy session and redirect to login
	 */
	public function executeLogout()
	{
		Auth::removeIdentity();
		
		Common::redirect(URL_LOGIN);
	}
	
	
	/**
	 * execute user change password 
	 */
	public function executeChangePassword()
	{
		// initialize message to view
		$this->errorMessage = '';
		$this->notifyMessage = '';
		$errors = array();
      	
      // user has not logged in, redirect to login
		if(!Auth::hasIdentity()) { Common::redirect(URL_LOGIN); }
		
		// retrieve account data of user
		$userData = Auth::getIdentity();
		$account_id = $userData->account_id;

		// form submission processing
		if (isset($_POST['submitChangePassword'])) {
			// initialize vars
			$password = $_POST['pass'];
			$confpassword = $_POST['confpass'];

			// password change process
			// validate entry in password change
			if (empty($password) || empty($confpassword)) {
				$errors[] = "Both Change Password and Confirm Password must not be empty.";
			} else {
				$min = 3;
				if (!Validator::isStringLength($password, $min, null)) {
					$errors[] = "Change Password must be at least {$min} characters long.";
				}

				if ($password != $confpassword) {
					$errors[] = 'Change Password and Confirm Password do not match.';
				}
			}

			if(empty($errors)) {

				//true, update password change
				$user = new User($account_id);
				if ($user->isLoaded()) {
					$user->password = md5($password);
					$user->update();

					$this->notifyMessage = 'Changes have been updated!';
				}
			}
			
		}
		
		// assigning for view
		$this->errorMessage = current($errors);
		
	}
	
	/**
	 * user profile
	 * 
	 * on form submission
	 * in account fieldset, validate input, 
	 * if no issues, update password change.
	 * in profile fieldset, validate input,
	 * if no issues, update profile changes.
	 */
	public function executeUpdate()
	{	
		// initialize message to view
		$this->errorMessage = '';
		$this->notifyMessage = '';
		$errors = array();
		
      	
      // user has not logged in, redirect to login
		if(!Auth::hasIdentity()) { Common::redirect(URL_LOGIN); }
		
		// retrieve account data of user and profile data
		$user = Auth::getIdentity();
		$profile = Profile::findProfileByAccountId($user->account_id);
		

		// form submission processing
		if (isset($_POST['submitProfile'])) {

			// initialize form profile vars
			$name = $_POST['name'];
			$gender = (isset($_POST['gender'])) ? $_POST['gender'] : null;
			$address = $_POST['address'];
			$city = $_POST['city'];
			$state = $_POST['state'];
			$postal = $_POST['postal'];
			$phone = $_POST['phone'];
			$email = $_POST['email'];
			$dob = (isset($_POST['dob'])) ? $_POST['dob'] : null;

			if (empty($errors)) {
				// update profile data
				$profile->user_name = $name;
				$profile->user_gender = $gender;
				$profile->user_address = $address;
				$profile->user_city = $city;
				$profile->user_state = $state;
				$profile->user_postal = $postal;
				$profile->user_phone = $phone;
				$profile->user_email = $email;
				$profile->user_dob = $dob;
				$profile->update();

				$this->notifyMessage = 'Changes have been updated!';
			}
		}
		
		// assigning for view
		$this->errorMessage = current($errors);
		$this->profile = $profile;
		$this->user = $user;
	}
	
	/**
	 * User profile
	 * 
	 * check on the profile uri e.g. /user/profile/adam
	 * if param contains an value (e.g. adam), 
	 * retrieve the value and check against the username on record
	 * if username exists, display profile details
	 * 
	 * if param has no value, then it will check if user is logged in
	 * if true, then user will own profile
	 * if not, user will be prompt to login
	 */
	public function executeProfile()
	{
		// initialize vars
		$limitShareCount = 5;
		$addFriendLink = '';
		
		$type = @$_GET['t'];
		
		// check if the param (username) exists
		$username = Common::getParam(0);
		if ($username) {
			// check if the user exists in database
			$user = User::findByUsername($username);
			$profile = Profile::findProfileByAccountId($user['account_id']);
			$activities = Share::findByAccountId($user['account_id'], $limitShareCount);
			
			// if no such user, prompt flash message
			if (!$user) {
				// set message
				Common::error("You are trying to access the profile of an invalid user.");
			}
		} else {
			// show own profile
			// there is such user, check if the current user is logged in
			// not logged in, redirect to login
			if(!Auth::hasIdentity()) Common::redirect (URL_LOGIN);

			// logged in, retrieve user identity, profile and activities
			$user = Auth::getIdentity();
			$profile = Profile::findProfileByAccountId($user->account_id);
			$activities = Share::findByAccountId($user->account_id, $limitShareCount, $type);
		}

		// display to view
		$this->user = $user;
		$this->shareMessage = DataHelper::getShareMessage('Status', $user->account_id, 1);
		$this->profile = $profile;
		$this->activities = $activities;
		$this->type = $type;
	}
	
	
	/** 
	 * list of all available users
	 */
	public function executeList()
	{
		// find all available users
		$users = User::findByRecent();
		
		// set data to view
		$this->allUsers = $users;
	}

	/**
	 * add friend for user based on param on the url
	 * 
	 * get the param if it is available and not empty
	 * if true, proceed to check if user has auth
	 *		if true, check the friend's id based on the friend's username
	 *		if friend's id exists, add to friend db, and flash message to owner profile
	 * if not, redirect to login, with flash message
	 */
	public function executeAddFriend()
	{

		$uri = Common::getParam();
		
		// check if the username exists in uri
		if (isset($uri[0]) && Validator::isNotEmpty($uri[0])) {
			$username = $uri[0];

			// check if user is not logged in
			// if user not logged in, redirect them to login
			if (!Auth::hasIdentity()) {
				Common::flashMessage("You will need to login to add friends.");
				Common::redirect(URL_LOGIN);
			}
			
			// if user logged in, proceed to check the friend's username in existence
			$friend = User::findByUsername($username);
			if (!$friend) {
				Common::flashMessage("You have tried to add an invalid user as friend.");
				Common::redirect(URL_PROFILE);
			}
			
			// get user's id and friend's id
			$user = Auth::getIdentity();
			$account_id = $user->account_id;
			$account_friend_id = $friend->account_id;
			
			// check if user is currently a friend of the person he/she wishes to add
			$isfriend = User::isFriend($account_id, $account_friend_id);
			
			if ($isfriend) { 
				Common::flashMessage("You are already a friend of {$username}.");
				Common::redirect(URL_FRIENDS);
			}
			
			// create new Friend for user
			$user_addfriend = User::addFriend($account_id, $account_friend_id);
			
			if ($user_addfriend) {
				Common::flashMessage("You have successfully added {$username} as friend.");
				Common::redirect(URL_FRIENDS);
			}
		}
			
	}
	
	/**
	 * generate user's friend list 
	 */
	public function executeFriends()
	{
		// initialize vars
		$this->errorMessage = '';
		$this->notifyMessage = '';
		$this->allFriends = '';
		
		// if user is not logged in, prompt error
		if (!Auth::hasIdentity()) {
			$error[] = 'You are required to login to add friends.';
		}
		
		// if user is logged in, load the user's profile
		if (Auth::hasIdentity()) {
			$user = Auth::getIdentity();
			$account_id = $user['account_id'];
			$allFriends = DataHelper::getFriendList();
		}
		
		if (!empty($error)) {
			$this->errorMessage = current($error);
		}
		
		if (empty($allFriends)) { 
			$this->notifyMessage = 'Currently, you have no friends. You can start adding friends now!';
		}
		
		$this->allFriends = $allFriends;
	}
	
	/**
	 * generate friends who added user list 
	 */
	public function executeFriendsAdded()
	{
		// initialize vars
		$this->errorMessage = '';
		$this->notifyMessage = '';
		$this->allFriends = '';
		
		// if user is not logged in, prompt error
		if (!Auth::hasIdentity()) {
			$error[] = 'You are required to login to add friends.';
		}
		
		// if user is logged in, load the user's profile
		if (Auth::hasIdentity()) {
			$user = Auth::getIdentity();
			$account_id = $user['account_id'];
			$allFriends = DataHelper::getFriendsAddedUserList();
		}
		
		if (!empty($error)) {
			$this->errorMessage = current($error);
		}
		
		if (empty($allFriends)) { 
			$this->notifyMessage = 'Currently, there are no users adding you as friends yet.';
		}
		
		$this->allFriends = $allFriends;
	}

	/**
	 * delete friend based on the third uri of the url
	 * 
	 * if user is logged in, 
	 *		check if friend's username exists in database
	 *		if false, prompt error
	 *		if true, proceed to delete
	 * if not logged in,  
	 */
	public function executeDeleteFriend()
	{
		// initialize vars
		$this->errorMessage = '';
		
		$uri = Common::getParam();
		
		// check if the third param (username) of uri exists
		if (isset($uri[0]) && Validator::isNotEmpty($uri[0])) {
			// uri[3] which is the username param isset and has a value
			$friend_username = $uri[0];
			
			// check if user is not logged in
			// if user not logged in, redirect them to login
			if (!Auth::hasIdentity()) {
				Common::flashMessage("You will need to login to delete friends.");
				Common::redirect(URL_LOGIN);
			}
			
			// if user logged in, proceed to check the friend's username in existence
			$friend = User::findByUsername($friend_username);
			if (!$friend) {
				Common::flashMessage("You have tried to delete an invalid user as friend.");
				Common::redirect(URL_PROFILE);
			}
			
			// get user account_id and friend's account_id
			$user = Auth::getIdentity();
			$account_id = $user->account_id;
			$account_friend_id = $friend->account_id;

			// check if the friend to be deleted off is on user's friend list
			$isfriend = User::isFriend($account_id, $account_friend_id);
			
			if (!$isfriend) { 
				Common::flashMessage("{$friend_username} is not your friend, hence cannot be deleted from your friend list.");
				Common::redirect(URL_FRIENDS);
			}
			
			$user_deletefriend = User::deleteFriend($account_id, $account_friend_id);
			
			if ($user_deletefriend) { 	
				Common::flashMessage("You have successfully deleted {$friend_username} from your friend list.");
				Common::redirect(URL_FRIENDS);
			}

		}
		
	}
	
}
?>